/** 
 * CommandFrame.java
 * @author Lex
 * 2007-8-17 ����12:37:27
 */
package fun.ui.frames;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.io.IOException;
import java.io.PrintStream;
import java.io.StringReader;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JToolBar;

import org.lex.awt.Location;
import org.lex.expression.ui.TreePane;
import org.lex.swing.Swings;

import fun.parser.EvaluationException;
import fun.parser.LexerException;
import fun.parser.ast.AstParser;
import fun.parser.ast.node.base.AstNode;
import fun.parser.ast.node.base.Expression;
import fun.parser.lexer.Lexer;
import fun.parser.lexer.Token;
import fun.parser.postfix.PostfixParser;
import fun.parser.postfix.PostfixProgram;
import fun.parser.util.TokenUtils;
import fun.symtable.UserSymbolTable;
import fun.ui.FunMainFrame;
import fun.util.Log;

/*
 *replaced by  ConsoleFrame
 */
public class CommandFrame extends TextAreaFrame {
	private JToolBar mainToolBar = null;
	private JButton runButton = null;

	public CommandFrame(FunMainFrame mainframe) {
		super(mainframe);
		initialize();
	}

	private void initialize() {
	this.setTitle("Command");
	this.getPane().add(this.getMainToolBar(), BorderLayout.NORTH);
	// hook text-area key event
	this.getTextArea().addKeyListener(new KeyAdapter() {
	    @Override
	    public void keyPressed(KeyEvent e) {
		// CTRL + Enter
		if (KeyEvent.VK_ENTER == e.getKeyChar() && InputEvent.CTRL_DOWN_MASK == e.getModifiersEx()) {
		    handleInput();
		}
	    }
	});
    }

	private JToolBar getMainToolBar() {
		if (mainToolBar == null) {
			mainToolBar = new JToolBar();
			mainToolBar.add(getRunButton());
		}
		return mainToolBar;
	}

	private JButton getRunButton() {
		if (runButton == null) {
			runButton = new JButton();
			runButton.setText("Go");
			runButton.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					handleInput();
				}
			});
		}
		return runButton;
	}

	private ResultFrame result = null;

	private ResultFrame getResultFrame() {
		if (null == this.result)
			this.result = this.mainframe.getResultFrame();
		return result;
	}

	private Log log = null;

	private Log getLog() {
		if (null == log)
			log = this.mainframe.getLogFrame();
		return log;
	}

	private void handleInput() {
		String input = this.getTextArea().getText();
		if (null == input || 0 == (input = input.trim()).length()) {
			this.getTextArea().setText("");
			return;
		}
		// TODO �ƺ��������һЩ����"help","quit","draw"֮�������������
		try {
			// ��ʼ��������
			// this.lexerTest( input );
			// this.postfixParserTest( input );
			// this.astParserTest( input );
			this.evalueTest(input);
			this.getTextArea().setText("");
			getLog().fine(input + " process over\n");
		} catch (IOException e) {
			e.printStackTrace();
			getLog().error(e.getMessage());
		} catch (LexerException e) {
			e.printStackTrace();
			getLog().error(e);
		} catch (EvaluationException e) {
			e.printStackTrace();
		}
	}

	private Lexer lexer = new Lexer();

	void lexerTest(String input) throws IOException, LexerException {
		lexer.setSource(new StringReader(input));
		Token t = null;
		getResultFrame().appene(input + " :\n");
		while (true) {
			t = lexer.nextToken();
			if (null == t || true == TokenUtils.isEnd(t))
				break;
			getResultFrame().appene('\t' + t.toString() + '\n');
		}
	}

	PostfixParser postfix = new PostfixParser();

	void postfixParserTest(String input) throws IOException, LexerException {
		postfix.setSource(new StringReader(input));
		PostfixProgram exp = postfix.parse();
		getResultFrame().appene(input + " :\n\t");
		getResultFrame().appene(exp.toString()).appene("\n");
	}

	AstParser ast = new AstParser();

	void astParserTest(String input) throws IOException, LexerException {
		PostfixParser postfix = new PostfixParser();
		postfix.setSource(new StringReader(input));
		PostfixProgram exp = postfix.parse();
		AstNode root = ast.parse(exp);
		root.print(new PrintStream(getResultFrame().getTextArea().getOutputStream()), 4);
		this.showAst(root);
	}

	TreePane tree = null;

	void showAst(AstNode root) {
		if (null == tree) {
			tree = new TreePane();
			JFrame frame = new JFrame("AST");
			frame.setContentPane(tree);
			frame.setSize(300, 500);
			Location.moveTo(frame, Location.SOUTH_EAST);
			frame.setVisible(true);
		}
		tree.setRootNode(root);
		Swings.expandAll(tree.getTree());
	}

	void evalueTest(String input) throws IOException, LexerException, EvaluationException {
		PostfixParser postfix = new PostfixParser();
		postfix.setSource(new StringReader(input));
		PostfixProgram exp = postfix.parse();
		Expression expr = ast.parse(exp);
		getResultFrame().appene(input + " :\n\t");
		getResultFrame().appene(expr.getValue(UserSymbolTable.getInstance())).appene("\n");
	}
}
